package com.dk.smsexpress.server.imp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dk.smsexpress.common.base.MobiAccount;
import com.dk.smsexpress.common.exception.ExceptionConstant;
import com.dk.smsexpress.common.exception.SmsException;

public class MobiSms {
	final static Logger logger = LoggerFactory.getLogger(MobiSms.class);

	private final String USER_AGENT = "Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";
	private final String ROUTE_ID1 = "RouteID=route.neo_srv01;";
	// final String ROUTE_ID2 = "RouteID=route.neo_srv02;";
	private final String MOBI_AUTHENTICATE_URL = "http://www.mobifone.com.vn/web/vn/users/authenticate.jsp";
	private final String MOBI_SMS_URL = "http://www.mobifone.com.vn/web/vn/sms/result.jsp";
	private final String MOBI_SMS_REFERER = "http://www.mobifone.com.vn/web/vn/sms/";
	private final String MOBI_ADV_URL = "http://www.mobifone.com.vn/web/vn/sms/";
	private final String MOBI_ADV_REFERER = "http://www.mobifone.com.vn/web/vn/";

	private final String LOGIN_SUCCESS_MESSAGE = "&#272;&#259;ng nh&#7853;p th&#224;nh c&#244;ng";

	private String phoneNum;
	private String username;
	private String password;
	private String message;
	private int messageLeft;

	private String jsessionid = "";
	private URLConnection conn;
	private OutputStreamWriter wr;
	private URL url;
	private BufferedReader rd;
	private StringBuffer data;
	private StringBuffer response;
	private String advStr;
	private String cookies;
	private MobiAccount account;

	public MobiSms(MobiAccount account) throws SmsException, IOException {
		this.username = account.getUsername();
		this.password = account.getPassword();
		this.account = account;
		performLogin();
		getInitData();
		account.setMessageLeft(messageLeft);
	}

	public int getMessageLeft() {
		return messageLeft;
	}

	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	private void performLogin() throws SmsException, IOException {

		logger.info("Perform Login");
		logger.debug("Account info:\nUsername:" + username + "\nPassword:"
				+ password);
		logger.debug("Phone Number:" + phoneNum + "\nMessage:" + message);

		data = new StringBuffer();
		data.append(URLEncoder.encode("username", HTTP.UTF_8) + "="
				+ URLEncoder.encode(username, HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("password", HTTP.UTF_8) + "="
				+ URLEncoder.encode(password, HTTP.UTF_8));

		// Send strData
		url = new URL(MOBI_AUTHENTICATE_URL);
		conn = url.openConnection();
		conn.setDoOutput(true);
		conn.addRequestProperty("Cookie", ROUTE_ID1);
		wr = new OutputStreamWriter(conn.getOutputStream());
		wr.write(data.toString());
		wr.flush();

		// Get the response
		rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		String line;
		response = new StringBuffer();
		while ((line = rd.readLine()) != null) {
			response.append(line);
		}
		logger.debug("Response:" + response);

		if (response.indexOf(LOGIN_SUCCESS_MESSAGE) == -1) {
			// Login unsuccessful
			throw new SmsException(ExceptionConstant.LOGIN_UNSUCCESSFUL);
		}

	}

	private void getInitData() throws IOException {
		// Get JSESSIONID
		StringBuffer cookieHeader = new StringBuffer();
		Map<String, List<String>> responseMap = conn.getHeaderFields();
		for (Iterator<String> iterator = responseMap.keySet().iterator(); iterator
				.hasNext();) {
			String key = (String) iterator.next();
			if (key != null) {
				if (key.toUpperCase().equals("set-cookie".toUpperCase())) {
					List<String> values = (List<String>) responseMap.get(key);
					for (int i = 0; i < values.size(); i++) {
						Object o = values.get(i);
						cookieHeader.append(o + ",");
					}
				}
			}
		}

		wr.close();
		rd.close();

		Pattern pattern = Pattern
				.compile("JSESSIONID=([\\.a-zA-Z_0-9]+);.*?path=([/\\.a-zA-Z_0-9]+),");
		Matcher matcher = pattern.matcher(cookieHeader);
		if (matcher.find()) {
			jsessionid = matcher.group(1);
		}

		cookies = new String(ROUTE_ID1 + "JSESSIONID=" + jsessionid
				+ ";username=" + username + ";");

		// Get AdvString
		advStr = "(www.mobifone.com.vn)";
		url = new URL(MOBI_ADV_URL);
		conn = url.openConnection();
		conn.addRequestProperty("User-Agent", USER_AGENT);
		conn.addRequestProperty("Referer", MOBI_ADV_REFERER);
		conn.addRequestProperty("Cookie", cookies);

		rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		response = new StringBuffer();
		String line;
		while ((line = rd.readLine()) != null) {
			response.append(line);
		}

		pattern = Pattern
				.compile(
						"javascript\\:checkstrData\\([0-9]+,'([\\.\\(\\)\\?;,a-zA-Z_0-9 /\\-\\%]+)'\\)",
						Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
		matcher = pattern.matcher(response);
		if (matcher.find()) {
			advStr = matcher.group(1);
		}

		// Get Number of free message left
		pattern = Pattern.compile(
				"<span class=\"more1\"><strong>(\\d+)</strong></span>",
				Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
		matcher = pattern.matcher(response);
		if (matcher.find()) {
			messageLeft = Integer.valueOf(matcher.group(1));
		}

	}

	public void sendMessage() throws SmsException, IOException {

		data = new StringBuffer();
		data.append(URLEncoder.encode("smsTplId", HTTP.UTF_8) + "="
				+ URLEncoder.encode("", HTTP.UTF_8));

		data.append("&" + URLEncoder.encode("mSelect", HTTP.UTF_8) + "="
				+ URLEncoder.encode("", HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("pbList", HTTP.UTF_8) + "="
				+ URLEncoder.encode("", HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("CCode", HTTP.UTF_8) + "="
				+ URLEncoder.encode("84", HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("phonenum", HTTP.UTF_8) + "="
				+ URLEncoder.encode(phoneNum, HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("message", HTTP.UTF_8) + "="
				+ URLEncoder.encode(message + advStr, HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("advFlg", HTTP.UTF_8) + "="
				+ URLEncoder.encode("ON", HTTP.UTF_8));
		data.append("&" + URLEncoder.encode("chargeFlg", HTTP.UTF_8) + "="
				+ URLEncoder.encode("1", HTTP.UTF_8));

		url = new URL(MOBI_SMS_URL);
		conn = url.openConnection();
		conn.setDoOutput(true);
		conn.addRequestProperty("User-Agent", USER_AGENT);
		conn.addRequestProperty("Referer", MOBI_SMS_REFERER);
		conn.addRequestProperty("Cookie", cookies);
		wr = new OutputStreamWriter(conn.getOutputStream());
		wr.write(data.toString());
		wr.flush();

		// Get the response
		rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		response = new StringBuffer();
		String line;
		while ((line = rd.readLine()) != null) {
			response.append(line);
		}
		Pattern pattern = Pattern.compile(phoneNum.substring(3) + "[\\s]+",
				Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
		Matcher matcher = pattern.matcher(response);
		if (matcher.find()) {
			return;
		}
		wr.close();
		rd.close();
		
		
		account.setMessageLeft(account.getMessageLeft()-1);
	}
}
